﻿#pragma once

#include "Common.h"
#include "VirtualEvent.h"
#include "ThreadLocalStorage.h"

#include "../interface/Logger.h"
#include "../common/ScriptApplication.h"

namespace cmdline { class parser; };

// lua-md5 lib
extern "C" int luaopen_md5_core(lua_State * L);
extern "C" int luaopen_des56(lua_State * L);

#ifdef USE_LSQLITE
extern "C" int luaopen_lsqlite3(lua_State * L);
#endif // USE_LSQLITE

#ifdef USE_LUA_CJSON
extern "C" int luaopen_cjson(lua_State * L);
#endif

#ifdef USE_LUV
extern "C" int luaopen_luv(lua_State * L);
#endif

#ifdef USE_LUA_CURL
extern "C" int luaopen_lcurl(lua_State * L);
extern "C" int luaopen_lcurl_safe(lua_State * L);
#endif

#ifdef USE_LUA_EXPAT
extern "C" int luaopen_lxp(lua_State* L);
#endif
namespace LuaGui {
	class Paint;

	class Application {
	public:
		Application();
		~Application();

		static Application* GetInstance() {
			if (!s_application) s_application = new Application();
			return s_application;
		}

		virtual void Init(int argc, char* argv[]);
		virtual void OnInit();
		virtual void Exit() { OnExit(); }
		virtual void OnExit();                                                                       // 程序退出
		virtual void OnWindowSize();                                                                 // 窗体大小改变事件
		virtual void OnScreenSize();                                                                 // 窗体大小改变事件
		virtual void Render() {}                                                                     // 绘图事件
		virtual void OnTimer();                                                                      // 定时回调
		virtual void OnMouse(std::shared_ptr<VirtualMouseEvent> e);                                  // 鼠标事件
		virtual void OnMouseDown(int mouse_x, int mouse_y, int mouse_button = 0);                    // 鼠标按下事件
		virtual void OnMouseMove(int mouse_x, int mouse_y);                                          // 鼠标移动事件
		virtual void OnMouseUp(int mouse_x, int mouse_y, int mouse_button = 0);                      // 鼠标松开事件
		virtual void OnMouseWheel(int mouse_x, int mouse_y, int mouse_wheel_delta = 0);              // 鼠标滚动事件
		virtual void OnKey(std::shared_ptr<VirtualKeyEvent> e);                                      // 按键事件
		virtual void OnKeyDown(unsigned int virtual_key);                                            // 键按下
		virtual void OnKeyUp(unsigned int virtual_key);                                              // 键松开
		virtual void OnChar(std::shared_ptr<VirtualCharEvent> e);                                    // 输入字符  
		virtual void OnNet(void* socket, void* data) {}                                              // 网络回调
		virtual void OnCurl(unsigned long uid, std::string data) {}                                  // curl 回调
		virtual bool LoadAsset(std::string filepath, std::vector<int8_t>& buff);                     // 加载资源
		virtual std::string GetAssetTextByFilePath(std::string filepath);                            // 加载脚本
		virtual std::string GetScriptTextByFilePath(std::string filepath);                           // 加载脚本
		virtual std::string GetTextByFilePath(std::string filepath);                                 // 获取文件文本
		virtual std::string GetClipboardText() { return ""; }
		virtual bool SetClipboardText(std::string text) { return false; }
		virtual void StartTextInput() {}
		virtual void StopTextInput() {}
		virtual void SetTextInputRect(int x, int y, int w, int h) {}

		virtual void Loop();                                                                         // 事件循环
		virtual void OnLoopOnce();                                                                   // 事件循环一次

		bool IsDevEnv() { return m_dev_env; }                                                        // 是否开发环境
		void SetDevEnv(bool is_dev_env) { m_dev_env = is_dev_env; }                                  // 设置开发环境
		std::string& GetEnv() { return m_env; }

		// platform
		virtual bool IsWin32() { return false; }
		virtual bool IsMac() { return false; }
		virtual bool IsLinux() { return false; }
		virtual bool IsAndroid() { return false; }
		virtual bool IsIos() { return false; }
		virtual bool IsConsole() { return false; }

		virtual void ShowIME() {}; // 显示输入法
		virtual void HideIME() {}; // 隐藏输入法

		virtual LuaScriptApplication* GetScriptApplicationInstance() { return LuaScriptApplication::GetMainInstance(); }
		virtual Paint* GetPaint() { return NULL; }                                                  // 获取绘图对象
	public:
		void StartScript();

		std::string GetCurrentThreadStringId();
		std::string GetMainThreadStringId();

		std::string GetMainThreadName() { return "__main__"; }
		ThreadLocal* GetMainThreadLocal() { return m_main_thread_local; }

		void InitCmdLine();                                                                          // 初始化命令行
		void ParseCmdLine();                                                                         // 解析命令行

		virtual std::string GetReadWriteDirectory();  // 获取可读可写目录, 且必须为绝对路径
		inline fs::path& GetStorageDirectory() { return m_storage_directory; }
		inline void SetStorageDirectory(fs::path path) { m_storage_directory = path; }
		inline fs::path& GetVirtualDirectory() { return m_virtual_directory; }
		inline void SetVirtualDirectory(fs::path path) { m_virtual_directory = path; }
		inline fs::path& GetPackageDirectory() { return m_package_directory; }
		inline void SetPackageDirectory(fs::path path) { m_package_directory = path; }
		inline fs::path& GetAssetDirectory() { return m_asset_directory; }
		inline void SetAssetDirectory(fs::path path) { m_asset_directory = path; }
		inline fs::path& GetScriptDirectory() { return m_script_directory; }
		inline void SetScriptDirectory(fs::path path) { m_script_directory = path; }
		inline fs::path& GetBootstrapper() { return m_bootstrapper; }
		inline fs::path& GetLogFilePath() { return m_log_filepath; }
		inline void SetLogFilePath(fs::path path) { m_log_filepath = path; }
		inline fs::path& GetFontFilePath() { return m_font_filepath; }

		int GetScreenWidth() { return m_screen_width; }
		int GetScreenHeight() { return m_screen_height; }
		void SetScreenWidth(int width);
		void SetScreenHeight(int height);
		void SetScreenWidthHeight(int width, int height);

		int GetWindowWidth() { return m_window_width; }
		int GetWindowHeight() { return m_window_height; }
		void SetWindowWidthHeight(int width, int height);
		void SetWindowWidth(int width);
		void SetWindowHeight(int height);
		float GetWindowScale() { return m_window_scale; }
		void SetWindowScale(float scale) { m_window_scale = scale; }
		unsigned int GetTimerInterval() { return m_timer_interval; }

		virtual std::string GetAppName() { return m_app_name; }
		virtual void SetAppName(std::string app_name) { m_app_name = app_name; }
		virtual std::string GetWindowTitle() { return m_window_title; }
		virtual void SetWindowTitle(std::string window_title) { m_window_title = window_title; }

		// logger
		virtual LuaGui::Logger* GetConsoleLogger() { return LuaGui::ConsoleLogger::GetSingleton(); }
		virtual void Debug(std::string msg);
		virtual void Info(std::string msg);
		virtual void Warn(std::string msg);
		virtual void Error(std::string msg);
	protected:
		static Application* s_application;                                                           // 全局示例
		cmdline::parser* m_cmdline;                                                                  // 命令行解析器
		std::string m_app_name;
		std::string m_window_title;
		// path 
		fs::path m_log_filepath;                                                                     // 日志文件路径
		fs::path m_font_filepath;                                                                    // 字体文件路径
		fs::path m_bootstrapper;                                                                     // 启动脚本
		fs::path m_storage_directory;                                                                // 存贮目录 
		fs::path m_package_directory;                                                                // 脚本包目录
		fs::path m_script_directory;                                                                 // 脚本包目录
		fs::path m_asset_directory;                                                                  // 资源目录
		fs::path m_virtual_directory;                                                                // 虚拟目录 只读不写 用于内置内存数据

		// 屏幕大小
		int m_screen_width;
		int m_screen_height;
		// 窗口大小
		int m_window_width;
		int m_window_height;
		// 窗口缩放比
		float m_window_scale;

		// loop
		bool m_exited;                                                                              // 是否退出
		unsigned int m_timer_interval;                                                              // 定时间隔
		bool m_dev_env;                                                                             // 编译环境

		std::string m_env;                                                                          // 环境

		ThreadLocal* m_main_thread_local;                                                           // 主线程局部存贮
	protected:
		static std::string LuaGuiVirtaulPath;                // 文件系统根目录
		static std::string LuaGuiAssetPath;                  // 安卓asset专用目录
		static std::string LuaGuiScriptPath;                 // 脚本目录名
		static std::string LuaGuiPackagePath;                // 包目录名
		static std::string LuaGuiFontPath;                   // 脚本目录名
		static std::string LuaGuiLogPath;                    // 脚本目录名
	};

}

